import log.Logger;
import log.SimpleLogger;
import philosoph.Philosoph;
import philosoph.StdPhilosoph;
import table.RoundWalkingTable;
import table.Table;
import warden.EatAmountWarden;
import warden.EatTimeWarden;
import warden.SimpleEatAmountWarden;
import warden.SimpleEatTimeWarden;


public class Application {

	public static void main(String[] args) throws InterruptedException {
		if (args.length % 2 == 0) {
			System.out.println("invalid amount of arguments");
			return;
		}
		int runTime = Integer.parseInt(args[0]);
		int difference = Integer.parseInt(args[1]);
		int stallTime = Integer.parseInt(args[2]);
		int maxEatTime = Integer.parseInt(args[3]);
		int seats = Integer.parseInt(args[4]);
		final Logger logger = new SimpleLogger();

		final Philosoph[] philosophs = new Philosoph[((args.length - 4) >> 1)];
		for (int i = 0; i < philosophs.length; i++) {
			philosophs[i] = new StdPhilosoph(Integer.parseInt(args[5 + (2 * i)]), Integer.parseInt(args[6 + (2 * i)]), logger);
		}
		final EatAmountWarden<Philosoph> eatAmountWarden = new SimpleEatAmountWarden<Philosoph>(logger, stallTime, difference, philosophs);
		final EatTimeWarden<Philosoph> eatTimeWarden = new SimpleEatTimeWarden<Philosoph>(logger, maxEatTime);
		final Table<Philosoph> table = new RoundWalkingTable<Philosoph>(seats, eatTimeWarden, eatAmountWarden, logger);
		Thread[] threads = new Thread[philosophs.length];
		for (int i = 0; i < philosophs.length; i++) {
			final Philosoph phil = philosophs[i];
			threads[i] = new Thread(new Runnable() {
				
				@Override
				public void run() {
					try {
						while(true) {
							phil.think();
							table.sitNEat(phil);
						}
					} catch (InterruptedException e) {
						// TODO: handle exception
					}
				}
			});
			threads[i].setDaemon(true);
		}
		for (Thread t : threads) {
			t.start();
		}
		Thread.sleep(runTime);
		for (Thread t : threads) {
			t.interrupt();
		}
		for (Thread t : threads) {
			t.join(1000);
		}
	}

}
